﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace KaartenLib{

    public delegate void LegeLijstEventHandler(object sender, EventArgs e);

    public class KaartSpel : ICloneable,IEnumerable<Kaart>{
        List<Kaart> kaarten = new List<Kaart>();
        private Random random = new Random();
        public event LegeLijstEventHandler LegeLijst;        

        public KaartSpel(){
            for (int i = 0; i < 4; i++){
                for (int j = 1; j < 14; j++) {
                    VoegKaartToe(new Kaart((KaartSoort)i,(KaartWaarde)j));
                }
            }           
        }

        public KaartSpel(ICollection<Kaart> col){
            VoegKaartenToe(col);
        }

        public List<Kaart> Kaarten{
            get{
                return kaarten;
            }
            set{
                kaarten = value;
            }
        }

        public int AantalKaarten(){
            return kaarten.Count;
        }

        public virtual void VoegKaartToe(Kaart kaart){
            if (kaarten != null){
                if (!kaarten.Contains(kaart)){
                    kaarten.Add(kaart);

                }else{
                    throw new InvalidOperationException("Er is al reeds een kaart in het spel dezelfde waarde en soort hebben!");
                }
            }else{
                throw new InvalidOperationException("Er bestaat nog geen lijst met kaarten!");
            }
        }

        public void VoegKaartenToe(ICollection<Kaart> kaarten){
            foreach (Kaart k in kaarten){
                VoegKaartToe(k);
            }            
        }

        public Kaart TrekRandomKaart() {          
            int i = random.Next(kaarten.Count);
            return TrekKaart(i);
        }       

        public Kaart TrekBovensteKaart(){
            int i = this.AantalKaarten() - 1;
            return TrekKaart(i);
        }

        public Kaart TrekKaart(int index){
            if (index >= 0 && index < AantalKaarten())
            {
                Kaart kaart = kaarten[index];
                kaarten.Remove(kaart);
                if (kaarten.Count == 0)
                {
                    OnChange(EventArgs.Empty);
                }
                else {
                    bool lastSort = true;
                    foreach (var k in kaarten)
                    {
                        if (k.Soort == kaart.Soort) {
                            lastSort = false;
                        }
                    }
                    if (lastSort)
                    {
                        OnChange(new LegeLijstEvent("We run out of " + kaart.Soort));
                    }
                }
                return kaart;
            }else{
                throw new ArgumentOutOfRangeException("index", index, "index moet liggen tussen 0 en " + (AantalKaarten() - 1));
            }
        }

        protected virtual void OnChange(EventArgs e)
        {
            if (LegeLijst != null){
                LegeLijst(this, e);
            }
        }
        //•	Maak een methode om het kaarxtspel te schudden

        public void Schudden()
        {
            List<Kaart> nieuweKaarten = new List<Kaart>();
            while (kaarten.Count > 0)
            {
                int hulpKaart = random.Next(kaarten.Count);
                nieuweKaarten.Add(kaarten[hulpKaart]);
                kaarten.RemoveAt(hulpKaart);
            }
            kaarten = nieuweKaarten;
        }

        //•	Kaartspel moet (deep) cloneable zijn
        public Kaart ZoekKaart(int index){
            return this[index];
        }

        public Kaart ZoekKaart(KaartWaarde waarde, KaartSoort soort){
            Kaart uit= new Kaart();
            foreach(Kaart k in kaarten){
                if (k.Soort == soort && k.Waarde == waarde){
                    return k;
                }
            }
            return null;
        }

        public void SorteerKaarten()
        {
            kaarten.Sort();
        }

        public void SorteerKaarten(KaartSoort [] volgorde)
        {
            kaarten.Sort(new KaartenComparerMetEigenVolgorde(volgorde));
        } 

        public override string ToString()
        {
            string terug = "Aantal kaarten: " + AantalKaarten() + Environment.NewLine;
            foreach (Kaart kaart in kaarten)
            {
                terug += kaart.ToString() + Environment.NewLine;
            }
            return terug;
        }
        ////TODO        
        //•	Kaartspel vuurt een event af als de laatste kaart van een bepaald type wordt getrokken

        public Object Clone()
        {
            List<Kaart> newKaarten = new List<Kaart>();
            foreach (Kaart k in kaarten)
            {
                Kaart cloneK = (Kaart)k.Clone();
                newKaarten.Add(cloneK);
            }
            return newKaarten;
        }

        public Kaart this[int kaartIndex] {
            set {
                kaarten[kaartIndex] = value;
            }
            get {
                return kaarten[kaartIndex];
            }
        }


        public IEnumerator<Kaart> GetEnumerator()
        {
            foreach (Kaart kaart in kaarten)
            {
                yield return kaart;
            }
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    } 
}
